package com.mvc;

import com.mvc.annotation.RequestMapping;
import com.mvc.annotation.ResponseBody;
import com.mvc.interceptor.*;
import com.spring.annotation.Controller;
import com.spring.bean.BeanDefinition;
import com.spring.context.impl.AbstractApplicationContext;
import javafx.util.Pair;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.*;

/**
 * 扫描所有controller ，并缓存
 */

@Slf4j
public class MvcApplicationContext {
	// url -> 请求方法的映射
	private final Map<String, Pair<Method,Object>> handlerMapping = new HashMap<>();
	
	// url -> 请求方法参数的映射
	private final Map<String, Parameter[]> parameterMapping = new HashMap<>();
	
	
	// url -> 拦截器链映射
	private final Map<String, HandlerExecutionChain> urlToHandlerChain = new HashMap<>();
	
	
	// 项目上下文的路径
	private String contextPath;
	
	
	public MvcApplicationContext(AbstractApplicationContext ac ,String contextPath) {
		this.contextPath = contextPath;
		
		log.info("开始准备mvc环境初始化");
		initHandler(ac);
		log.info("mvc初始化完成");
	}
	
	/**
	 * 获得请求uri对应的方法
	 */
	public Pair<Method,Object> getMethod(String uri){
		return handlerMapping.get(uri);
	}
	
	/**
	 * 获得请求uri对应的参数信息
	 */
	public Parameter[] getParameter(String uri){
		return parameterMapping.get(uri);
	}
	
	/**
	 * 检查有没有当前url 的映射
	 */
	public boolean hasUri(String uri){
		return handlerMapping.containsKey(uri);
	}
	
	
	/**
	 * 返回url 对应的拦截器，可能为null
	 */
	public HandlerExecutionChain getChain(String uri){
		return urlToHandlerChain.get(uri);
	}
	
	
	/**
	 * 初始化所有请求映射
	 */
	private void initHandler(AbstractApplicationContext ac){
		
		// 手动处理所有的 拦截器并建立拦截器链，如何自动处理？
		// EncodeInterceptor encodeInterceptor = new EncodeInterceptor();
		// CorsInterceptor corsInterceptor = new CorsInterceptor();
		// LoginInterceptor loginInterceptor = new LoginInterceptor();
		// JsonResponseInterceptor jsonResponseInterceptor = new JsonResponseInterceptor();
		// ExceptionInterceptor exceptionInterceptor = new ExceptionInterceptor();
		//
		// MappedHandlerInterceptor h1 = new InterceptorRegistration(encodeInterceptor).addIncludeUrl("*.do").getInterceptor();
		//
		// MappedHandlerInterceptor h2 = new InterceptorRegistration(corsInterceptor).addIncludeUrl("*.do").getInterceptor();
		//
		// // 登录拦截需要排除掉 login.do
		// MappedHandlerInterceptor h3 =
		// 		new InterceptorRegistration(loginInterceptor)
		// 				// .addIncludeUrl("*.do")             // 开发阶段去掉登录验证
		// 				.addExcludeUrl("*login.do")
		// 				.getInterceptor();
		//
		// MappedHandlerInterceptor h4 = new InterceptorRegistration(jsonResponseInterceptor).getInterceptor();
		//
		// MappedHandlerInterceptor h5 = new InterceptorRegistration(exceptionInterceptor).addIncludeUrl("*.do").getInterceptor();
		
		
		// 拿到所有的 MappedHandlerInterceptor  过滤拦截器
		List<String> interceptorNames = ac.getAllBeanNameByType(MappedHandlerInterceptor.class);
		
		ArrayList<MappedHandlerInterceptor> interceptors = new ArrayList<>(interceptorNames.size());
		for (String interceptorName : interceptorNames) {
			interceptors.add((MappedHandlerInterceptor)ac.getBean(interceptorName));
		}

		
		// 设置排序方法
		interceptors.sort(new Comparator<MappedHandlerInterceptor>() {
			@Override
			public int compare(MappedHandlerInterceptor o1, MappedHandlerInterceptor o2) {
				return o1.getOrder()-o2.getOrder();
			}
		});
		
		// 准备好一个 json 拦截器
		MappedHandlerInterceptor jsonResponseFilter = new InterceptorRegistration(new JsonResponseInterceptor()).getInterceptor();
		
		
		Collection<BeanDefinition> allBeanDefinition = ac.getAllBeanDefinition();
		for (BeanDefinition bd : allBeanDefinition) {
			Class<?> beanClass = bd.getBeanClass();
			
			// 没有Controller注解或者是接口的都忽略
			if(!beanClass.isAnnotationPresent(Controller.class) || beanClass.isInterface()){
				continue;
			}
			
			// 查找所有public 方法，非public 无视
			Method[] methods = beanClass.getMethods();
			for (Method method : methods) {
				if (!method.isAnnotationPresent(RequestMapping.class)){  //忽略没有配RequestMapping的方法
					continue;
				}
				
				RequestMapping annotation = method.getAnnotation(RequestMapping.class);
				String url =  this.contextPath + annotation.value();  // 没有default ，所有不会为null ，但可能为空字符串，不判断了
				
				
				if(handlerMapping.putIfAbsent(url,new Pair<Method,Object>(method,ac.getBean(bd.getBeanName()))) != null){
					log.error("该url 发生重复注册：{}",url);
					continue;   // 跳过后续操作
				}
				
				Parameter[] parameters = method.getParameters();
				
				parameterMapping.put(url,parameters);
				log.info("注册url:{}",url);
				
				
				HandlerExecutionChain chain = new HandlerExecutionChain();
				
				
				
				// 检查拦截器链,先就这样吧
				// if (h1.match(url)) {
				// 	chain.addInterceptor(h1);
				// }
				// if(h2.match(url)){
				// 	chain.addInterceptor(h2);
				// }
				// if(h3.match(url)){
				// 	chain.addInterceptor(h3);
				// }
				//
				// if(method.isAnnotationPresent(ResponseBody.class) && !method.getReturnType().equals(Void.class)){
				// 	chain.addInterceptor(h4);
				// }
				//
				// if(h5.match(url)){
				// 	chain.addInterceptor(h5);
				// }
				
				// 遍历所有拦截器，符合条件添加
				for (MappedHandlerInterceptor interceptor : interceptors) {
					if(interceptor.match(url)){
						chain.addInterceptor(interceptor);
					}
				}
				
				// 最后额外检查一下 json 拦截器? 太耦合了
				if(method.isAnnotationPresent(ResponseBody.class) && !method.getReturnType().equals(Void.class)){
					chain.addInterceptor(jsonResponseFilter);
				}
				
				
				if(chain.getInterceptors().length != 0){
					urlToHandlerChain.put(url,chain);
					chain = new HandlerExecutionChain();
				}
			}
		}
	}
}
